/*
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership.  The ASF licenses this file
 to you under the Apache License, Version 2.0 (the
 "License"); you may not use this file except in compliance
 with the License.  You may obtain a copy of the License at
 
 http://www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an
 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 */

//
//  AppDelegate.m
//  PushInappTestiOS
//
//  Created by ___FULLUSERNAME___ on ___DATE___.
//  Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
//

#import "AppDelegate.h"
#import "MainViewController.h"
#import "JSON.h"
#import "AppManager.h"
#import <Cordova/CDVPlugin.h>

#define UUID_USER_DEFAULTS_KEY @"UUID"

@implementation AppDelegate

@synthesize window, viewController;

- (id)init
{
    /** If you need to do any extra app-specific initialization, you can do it here
     *  -jm
     **/
    NSHTTPCookieStorage* cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    
    [cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
    
    self = [super init];
    return self;
}

#pragma UIApplicationDelegate implementation

/**
 * This is main kick off after the app inits, the views and Settings are setup here. (preferred - iOS4 and up)
 */
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    [self checkDeviceUDID];
    
    NSURL* url = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
    NSString* invokeString = nil;
    
    if (url && [url isKindOfClass:[NSURL class]]) {
        invokeString = [url absoluteString];
        NSLog(@"PushInappTestiOS launchOptions = %@", url);
    }
    
    CGRect screenBounds = [[UIScreen mainScreen] bounds];
    self.window = [[[UIWindow alloc] initWithFrame:screenBounds] autorelease];
    self.window.autoresizesSubviews = YES;
    
    self.viewController = [[[MainViewController alloc] init] autorelease];
    self.viewController.useSplashScreen = YES;
    self.viewController.wwwFolderName = @"www";
    self.viewController.startPage = @"index.html";
    self.viewController.invokeString = invokeString;
    
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    
    // NOTE: To control the view's frame size, override [self.viewController viewWillAppear:] in your view controller.
    
    // check whether the current orientation is supported: if it is, keep it, rather than forcing a rotation
    BOOL forceStartupRotation = YES;
    UIDeviceOrientation curDevOrientation = [[UIDevice currentDevice] orientation];
    
    if (UIDeviceOrientationUnknown == curDevOrientation) {
        // UIDevice isn't firing orientation notifications yet… go look at the status bar
        curDevOrientation = (UIDeviceOrientation)[[UIApplication sharedApplication] statusBarOrientation];
    }
    
    if (UIDeviceOrientationIsValidInterfaceOrientation(curDevOrientation)) {
        if ([self.viewController supportsOrientation:curDevOrientation]) {
            forceStartupRotation = NO;
        }
    }
    
    if (forceStartupRotation) {
        UIInterfaceOrientation newOrient;
        if ([self.viewController supportsOrientation:UIInterfaceOrientationPortrait]) {
            newOrient = UIInterfaceOrientationPortrait;
        } else if ([self.viewController supportsOrientation:UIInterfaceOrientationLandscapeLeft]) {
            newOrient = UIInterfaceOrientationLandscapeLeft;
        } else if ([self.viewController supportsOrientation:UIInterfaceOrientationLandscapeRight]) {
            newOrient = UIInterfaceOrientationLandscapeRight;
        } else {
            newOrient = UIInterfaceOrientationPortraitUpsideDown;
        }
        
        NSLog(@"AppDelegate forcing status bar to: %d from: %d", newOrient, curDevOrientation);
        [[UIApplication sharedApplication] setStatusBarOrientation:newOrient];
    }
    
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    
    /*
     * m_userInfo의 상태에 따라 분기합니다.
     * nil : Push메시지로 인해 실행된 것이 아님.
     * !nil : Push메시지로 인해 실행됨
     */
    m_userInfo = [launchOptions objectForKey:
                  UIApplicationLaunchOptionsRemoteNotificationKey];
    isPush = NO;
    
    if(m_userInfo != nil)
    {
        isPush = YES;
    }
    
    [self addPushNotification];
    
    /*
     * Phonegap에서 DeviceReady 이벤트가 발생하면 BridgePlugin으로 메시지를 전달합니다.
     * 다시 BridgePlugin에서는 Notification을 이용하여 기기 정보를 전달하는 함수를 호출합니다.
     */
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(sendDeviceInfoToServer)
                                                 name:@"DEVICE_READY"
                                               object:nil];
    return YES;
}

// this happens while we are running ( in the background, or from within our own app )
// only valid if PushInappTestiOS-Info.plist specifies a protocol to handle
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url
{
    if (!url) {
        return NO;
    }
    
    // calls into javascript global function 'handleOpenURL'
    NSString* jsString = [NSString stringWithFormat:@"handleOpenURL(\"%@\");", url];
    [self.viewController.webView stringByEvaluatingJavaScriptFromString:jsString];
    
    // all plugins will get the notification, and their handlers will be called
    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];
    
    return YES;
}

- (NSUInteger)application:(UIApplication*)application supportedInterfaceOrientationsForWindow:(UIWindow*)window
{
    // iPhone doesn't support upside down by default, while the iPad does.  Override to allow all orientations always, and let the root view controller decide what's allowed (the supported orientations mask gets intersected).
    NSUInteger supportedInterfaceOrientations = (1 << UIInterfaceOrientationPortrait) | (1 << UIInterfaceOrientationLandscapeLeft) | (1 << UIInterfaceOrientationLandscapeRight) | (1 << UIInterfaceOrientationPortraitUpsideDown);
    
    return supportedInterfaceOrientations;
}

/*
 * 어플리케이션이 실행중일 때(화면에 보일 때) Push 메시지가 오면 호출됩니다.
 * MainViewController의 send함수를 호출합니다.
 */
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    NSLog(@"%s", __FUNCTION__);
    m_userInfo = [[[NSDictionary alloc]init]autorelease];
    m_userInfo = [userInfo copy];
    
    [(MainViewController*)self.viewController sendPushMessage:m_userInfo];
}

- (void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    NSLog(@"%s", __FUNCTION__);
    NSLog(@"Device Token : %@", deviceToken);
    NSString *token = [[[deviceToken description]
                        stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]
                       stringByReplacingOccurrencesOfString:@" "
                       withString:@""];
    
    m_deviceToken = [token retain];
}

- (void) application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    NSLog(@"%s", __FUNCTION__);
}

#pragma mark - User Define Function
- (void) addPushNotification
{
    @try {
        NSUInteger type = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound;
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:type];
    }
    @catch (NSException *exception) {
        [[AppManager getInstance] showAlertDialog:@"AppDelegate addPush" with:[exception reason]];
    }
    @finally {
        
    }
}

/*
 * DeviceReady 이벤트가 발생하면
 * Javascript로 DeviceID와 Token을 전송합니다.
 * Json 형태로 전송되며 COMMON_Event 함수를 호출합니다.
 * ex) {'token' : 'tokenvalue', 'udid' : 'udidvalue'}
 */
- (void) sendDeviceInfoToServer
{
    NSLog(@"%s", __FUNCTION__);
    @try {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSString *udid = [defaults objectForKey:UUID_USER_DEFAULTS_KEY];
        
        NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
        [dict setObject:@"deviceinfo" forKey:@"event"];
        [dict setObject:[NSString stringWithFormat:@"%@", m_deviceToken] forKey:@"token"];
        [dict setObject:[NSString stringWithFormat:@"%@", udid] forKey:@"udid"];
        
        [[AppManager getInstance] sendJavascript:@"COMMON_EVENT" data:dict];
        
        [dict release];
        
        if(isPush)
        {
            [((MainViewController*)self.viewController) sendPushMessage:m_userInfo];
        }
        
        [[NSNotificationCenter defaultCenter] removeObserver:self name:@"DEVICE_READY" object:nil];
    }
    @catch (NSException *exception) {
        [[AppManager getInstance] showAlertDialog:@"AppDelegate SaveInfo" with:[exception reason]];
    }
    @finally {
        
    }
}

/*
 * 현재 어플리케이션의 UserDefault를 조회하고, UDID값을 저장합니다.
 */
- (void) checkDeviceUDID
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    if ([defaults objectForKey:UUID_USER_DEFAULTS_KEY] == nil) {
        [defaults setObject:[self generateUDID] forKey:UUID_USER_DEFAULTS_KEY];
        [defaults synchronize];
    }
}

/*
 * MAC 어드레스를 기준으로 UDID를 생성합니다.
 * 이 값은 NSUserdefault에 저장됩니다.
 */
- (NSString *) generateUDID
{
    NSString *uuidString = nil;
    
    @try {
        CFUUIDRef uuid = CFUUIDCreate(NULL);
        if (uuid) {
            uuidString = (NSString *)CFUUIDCreateString(NULL, uuid);
            CFRelease(uuid);
        }
    }
    @catch (NSException *exception) {
        [[AppManager getInstance] showAlertDialog:@"AppDelegate UDID" with:[exception reason]];
    }
    @finally {

    }
    return [uuidString autorelease];
}
@end
